package lumis.portal.sendmail;

import lumis.util.log.ILogger;
import lumis.util.log.LoggerFactory;

/**
 * Thread used to process a mail queue. It spans {@link SendMailThread} to do
 * the actual mail sending.
 * 
 * @see #run()
 * @version $Revision: 6251 $ $Date: 2007-03-27 10:49:29 -0300 (Tue, 27 Mar 2007) $
 * @since 4.0.4
 */
class MailQueueProcessThread extends Thread
{
	/** System logger for this class. */
	private static ILogger logger = LoggerFactory.getLogger(MailQueueProcessThread.class);

	/**
	 * The id of the queue this thread processes.
	 * @since 4.0.4
	 */
	private final String queueId;
	
	/**
	 * The callback instance this thread sends notifications to.
	 * @since 4.0.4
	 */
	private final IMailQueueProcessThreadCallback callback;

	/**
	 * The interval in milliseconds to wait between mail sends.
	 * @since 4.0.4
	 */
	private final long sendInterval;

	/**
	 * The interval in milliseconds to wait between sending of {@link #blockSize} mails.
	 * @since 4.0.4
	 */
	private final long blockInterval;

	/**
	 * The number of mails that cause a pause of {@link #blockInterval} seconds.
	 * @since 4.0.4
	 */
	private final int blockSize;
	
	/**
	 * Creates a new MailQueueProcessThread.
	 * @param callback the instance this thread will send notifications to.
	 * @param queueId the id of the queue this thread will process.
	 * @param sendInterval the interval in seconds to wait between mail sends.
	 * @param blockInterval The interval in seconds to wait between sending of blockSize mails.
	 * @param blockSize the number of mails that cause a pause of blockInterval seconds.
	 * @since 4.0.4
	 */
	public MailQueueProcessThread(IMailQueueProcessThreadCallback callback, String queueId, int sendInterval, int blockInterval, int blockSize)
	{
		super("MailQueueProcessThread-" + queueId);
		this.queueId = queueId;
		this.callback = callback;
		this.sendInterval = sendInterval * 1000L;
		this.blockInterval = blockInterval * 1000L;
		this.blockSize = blockSize;
		setPriority(Thread.MIN_PRIORITY);
		setDaemon(true);
	}

	/**
	 * Sends all mails pending in the queue this thread is assigned to.
	 * <p>
	 * Performs sleeps as necessary to attend the blockInterval and sendInterval. 
	 * <p>
	 * The actual sending of the mails are executed by another thread spanned
	 * by this one, so this thread can be daemon but the sending is done by a
	 * non-daemon thread.
	 * @since 4.0.4
	 */
	@Override
	public void run()
	{
		try
		{
			int blockCount = 0;
			boolean queueHasPending = true;
			while (queueHasPending)
			{
				SendMailThread sendMailThread = new SendMailThread(callback, queueId);
				sendMailThread.start();
				// wait for the sendMailThread to terminate and obtain its
				// result
				sendMailThread.join();
				queueHasPending = sendMailThread.hasProcessedQueuedMail();

				if (queueHasPending)
				{
					// sleep for send interval
					sleep(sendInterval);

					// sleep for block interval if necessary
					blockCount++;
					if (blockSize > 0 && blockCount >= blockSize)
					{
						sleep(blockInterval);
						blockCount = 0;
					}
				}
			}

		}
		catch (InterruptedException e)
		{
			// thread was interrupted
			logger.debug(getName() + " interrupted", e);
		}
		
		// notify the termination of this thread
		callback.threadTerminated(queueId);
	}
}